package net.oschina.foodon.examples.spring.boot.amqp.producer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.CorrelationData;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.UUID;

/**
 * 消息发送器
 */
@Configuration
@Component
public class MessageSender {

    //主题名
    public static final String EXCHANGE = "rhis.topic";
    //队列名
    public static final String QUEUE_1 = "ehr-repository.queue";
    public static final String QUEUE_2 = "emr-repository.queue";
    //路由键名
    public static final String ROUTING_KEY_1 = "ehr";
    public static final String ROUTING_KEY_2 = "emr";

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private MessageConfirmCallback messageConfirmCallback;

    @Bean
    public MessageConverter jsonMessageConverter() {
        return new Jackson2JsonMessageConverter();
    }

    /**
     * 声明主题
     *
     * @return 声明的主题
     */
    @Bean
    public TopicExchange exchange() {
        return new TopicExchange(EXCHANGE);
    }

    /**
     * 声明队列
     *
     * @return 声明的队列
     */
    @Bean
    public Queue queue1() {
        return new Queue(QUEUE_1);
    }

    @Bean
    public Queue queue2() {
        return new Queue(QUEUE_2);
    }

    /**
     * 声明主题到队列的路由规则
     *
     * @return 声明的绑定
     */
    @Bean
    public Binding binding1() {
        return BindingBuilder
                .bind(queue1())
                .to(exchange())
                .with(ROUTING_KEY_1);
    }

    @Bean
    public Binding binding2() {
        return BindingBuilder
                .bind(queue2())
                .to(exchange())
                .with(ROUTING_KEY_2);
    }

    /**
     * 向消息队列1中发送消息
     *
     * @param msg 准备发送的消息文本
     */
    public void send1(String msg) {
        //设置发送成功回调
        this.rabbitTemplate.setConfirmCallback(messageConfirmCallback);

        //模拟业务主键
        String uuid = UUID.randomUUID().toString();
        CorrelationData correlationId = new CorrelationData(uuid);

        //发送
        rabbitTemplate.convertAndSend(EXCHANGE,
                ROUTING_KEY_1,
                this.buildMessage(msg),
                correlationId);
    }

    /**
     * 向消息队列2中发送消息
     *
     * @param msg 准备发送的消息文本
     */
    public void send2(String msg) {
        //设置发送成功回调
        this.rabbitTemplate.setConfirmCallback(messageConfirmCallback);

        //模拟业务主键
        String uuid = UUID.randomUUID().toString();
        CorrelationData correlationId = new CorrelationData(uuid);

        //发送
        rabbitTemplate.convertAndSend(EXCHANGE,
                ROUTING_KEY_2,
                this.buildMessage(msg),
                correlationId);
    }

    /**
     * 构造Message对象
     *
     * @param body 准备发送的字符串
     * @return Message对象
     */
    private Message buildMessage(String body) {
        //准备消息体
        byte[] messageBodyBytes = body.getBytes();

        //构造消息
        return MessageBuilder
                .withBody(messageBodyBytes)
                .setContentType("application/json")//MIME类型
                .setDeliveryMode(MessageDeliveryMode.PERSISTENT)//必须设置为持久消息
                .setPriority(1)//优先级
                .setTimestamp(new Date())//时间戳
                .setType("爱奥乐2017")//消息的类型，用于消费者解析
                .setMessageId("系统标识符.业务标识符")//生产者生成，使用系统标识符.业务主表主键形式，全局唯一，防重复消费
                .setAppId("chss-adapter-service")//生产者应用标识符
                .setHeader("example_key", "example_value")////根据业务需要自定义
                .build();
    }
}